package parteSemantica;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Iterator;
import java.util.LinkedList;

import parteLexica.Lexema;
import parteLexica.TabelaDeTokens.Token;
import parteSintatica.TabelaDeSimbolos;

public class AvaliadorExpressao {
	
	
	public AvaliadorExpressao () {
	}
	
//	public LinkedList<String> avaliarExpressao (LinkedList<Lexema> _listaLexemas) {
//		LinkedList<String> resultado = new LinkedList<String>();
//		
//		for (int i = 0;i < _listaLexemas.size();i++) {
//			if (_listaLexemas.get(i).getToken() == Token.LET) {
//				int tailExpressao = getIndexAtribuicao(i);
//				tabelaDeSimbolos.atribuirValor(_listaLexemas.get(i+1).getNome(), avaliarExpressao(getExpressao(tailExpressao)));
//				i = getIndexEndExpressao(tailExpressao) + 1;
//			} else if (_listaLexemas.get(i).getToken() == Token.IDENTIFICADOR) {
//				// busca pelo valor do identificador na tabela
//				
//				while (_listaLexemas.get(i).getToken() != Token.PONTO_E_VIRGULA_DUPLO) {
//					
//				}
//				
//			} else if (ehOperando(_listaLexemas.get(i))){
//				Lexema lexema = _listaLexemas.get(i);
//				TabelaDeTokens tokens = new TabelaDeTokens ();
//				if (tokens.ehOperadorBool(lexema.getToken())) {
//					
//				} else
//					
//				if (tokens.ehOperadorInt(lexema.getToken())) {
//					
//				} else 
//					
//				if (tokens.ehOperadorFloat(lexema.getToken())) {
//					
//				} else
//					
//				if (tokens.ehOperadorChar(lexema.getToken())) {
//					
//				} else 
//				1
//				if (tokens.ehOperadorString(lexema.getToken())) {
//					
//				}
//			}
//			
//		}
//		return resultado;
//	}
	
	
	public String avaliarExpressao(LinkedList<Lexema> lexemas, TabelaDeSimbolos tabela){
		LinkedList<Lexema> pilha = new LinkedList<Lexema>();
		LinkedList<Lexema> vetor = new LinkedList<Lexema>();
		LinkedList<Lexema> pilhaAux = new LinkedList<Lexema>();
		
		Iterator<Lexema> aux = lexemas.iterator();
		Lexema aux2;
		//Percorre a lista de lexemas
		while(aux.hasNext()){
			aux2 = aux.next();
			//Se for operando, bota na pilha
			if(aux2.getToken() == Token.VALOR_FLOAT || aux2.getToken() == Token.VALOR_INT ||  aux2.getToken() == Token.IDENTIFICADOR){
				vetor.add(aux2);
				//Se for operador:
			}else if(aux2.getToken() == Token.SOMA_INT || aux2.getToken() == Token.SOMA_FLOAT || aux2.getToken() == Token.SUBTRACAO_INT
					|| aux2.getToken() == Token.SUBTRACAO_FLOAT || aux2.getToken() == Token.MULTIPLICACAO_INT 
					|| aux2.getToken() == Token.MULTIPLICACAO_FLOAT ){
				//Se a pilha nao tiver vazia esvazia ela botando os operadores no vetor e adicionando o novo operador na pilha
				if(!pilha.isEmpty()){
					while(!pilha.isEmpty()){
						if(pilha.getFirst().getToken() == Token.ABRE_PARENTESIS)
							pilhaAux.addFirst(pilha.removeFirst());
						if(!pilha.isEmpty() && pilha.getFirst().getToken() == Token.ABRE_PARENTESIS)
							vetor.add(pilha.removeFirst());
					}
				while(!pilhaAux.isEmpty())
					pilha.addFirst(pilhaAux.removeFirst());
				pilha.addFirst(aux2);
				}else
					pilha.addFirst(aux2);
				//Se for abertura de parentese, joga na pilha
			}else if(aux2.getToken() == Token.ABRE_PARENTESIS)
				pilha.addFirst(aux2);
			//Se for fechamento de parenteses remove todos da pilha e bota no vetor até se axar abertura de parenteses
			else if(aux2.getToken() == Token.FECHA_PARENTESIS){
				while(!(pilha.getFirst().getToken() == Token.ABRE_PARENTESIS) || !pilha.isEmpty()){
					vetor.add(pilha.removeFirst());
					if(!pilha.isEmpty()){
						if(pilha.getFirst().getToken() == Token.ABRE_PARENTESIS){
							pilha.removeFirst();
							break;
						}
					}
				}
					
			}
		}
		
		//Esvazia a pilha e bota tudo no vetor
		
		while(!pilha.isEmpty()){
			if(pilha.getFirst().getToken() == Token.ABRE_PARENTESIS)
				pilhaAux.addFirst(pilha.removeFirst());
			if(!pilha.isEmpty())
			vetor.add(pilha.removeFirst());
		}
		
		//Cria-se uma pilha para guardar os valores
		LinkedList<String> pilhaValores = new LinkedList();
		
		Iterator<Lexema> iteradorVetor = vetor.iterator();
		
		//Percorre-se o vetor das expressões para análise
		while(iteradorVetor.hasNext()){
			aux2 = iteradorVetor.next();
			
			//Se aux2 é um operando coloca-os na pilha de valores
			if(aux2.getToken() == Token.VALOR_FLOAT || aux2.getToken() == Token.VALOR_INT ||  aux2.getToken() == Token.IDENTIFICADOR){
				if (aux2.getToken() == Token.IDENTIFICADOR){
					pilhaValores.addFirst(tabela.getVariavel(aux2.getNome()).getValor().top().getFirst());
				}else{
					pilhaValores.addFirst(aux2.getNome());
				}	
			}else if(aux2.getToken() == Token.SOMA_INT || aux2.getToken() == Token.SOMA_FLOAT || aux2.getToken() == Token.SUBTRACAO_INT
					|| aux2.getToken() == Token.SUBTRACAO_FLOAT || aux2.getToken() == Token.MULTIPLICACAO_INT 
					|| aux2.getToken() == Token.MULTIPLICACAO_FLOAT){
				float a = Float.parseFloat(pilhaValores.removeFirst());
				float b = Float.parseFloat(pilhaValores.removeFirst());
				
				if(aux2.getToken() == Token.SOMA_INT || aux2.getToken() == Token.SOMA_FLOAT){
					pilhaValores.addFirst(String.valueOf(a + b));
				}else if(aux2.getToken() == Token.SUBTRACAO_INT || aux2.getToken() == Token.SUBTRACAO_FLOAT){
					pilhaValores.addFirst(String.valueOf(a - b));
				}else if(aux2.getToken() == Token.MULTIPLICACAO_INT || aux2.getToken() == Token.MULTIPLICACAO_FLOAT){
					pilhaValores.addFirst(String.valueOf(a * b));
				}
				
			}
					
			}
			
	return pilhaValores.getFirst();	
	}
		
	
//	private LinkedList<Lexema> getExpressao (int index) {
//		LinkedList<Lexema> expressao = new LinkedList<Lexema>();
//		int ehEnd = 0;
//		int i = index;
//		while ((listaLexemas.get(i).getToken() != Token.PONTO_E_VIRGULA_DUPLO) || (ehEnd != 0)) {
//				if (listaLexemas.get(i).getToken() == Token.ATRIBUICAO) {
//					ehEnd++;
//				} 
//				if (listaLexemas.get(i).getToken() == Token.PONTO_E_VIRGULA_DUPLO){
//					ehEnd--;
//				}
//				expressao.add(listaLexemas.get(i));
//				i++;
//		}
//		expressao.add(listaLexemas.get(i));
//		return expressao;		
//	}
//	
//	private int getIndexEndExpressao (int index) {
//		int ehEnd = 0;
//		int i = index;
//		while ((listaLexemas.get(i).getToken() != Token.PONTO_E_VIRGULA_DUPLO) || (ehEnd != 0)) {
//				if (listaLexemas.get(i).getToken() == Token.ATRIBUICAO) {
//					ehEnd++;
//				} 
	
public void aval() throws IOException, InterruptedException{
	LineNumberReader in = new LineNumberReader(new InputStreamReader(System.in));
	String line = in.readLine();
	Process q = Runtime.getRuntime().exec(new String[]{"bash","-c","echo " + "\"" + line + "\"" + " > /home/diego/oc/Entrada"});
	Thread.sleep(100);
	Process p = Runtime.getRuntime().exec(new String[]{"bash","-c","ocaml < /home/diego/oc/Entrada > /home/diego/oc/Saida"});
	Thread.sleep(100);
	File file = new File("/home/diego/oc/Saida");
	LinkedList<String> lista = new LinkedList<String>();
	FileReader reader = new FileReader(file);
	BufferedReader buffer = new BufferedReader(reader);
	String linha = "";
	
	while(buffer.ready()){
		linha = buffer.readLine();
		lista.addFirst(linha);
	}
	buffer.close();
	reader.close();
	p.destroy();
	q.destroy();
	try{
	System.out.println(lista.get(1).substring(lista.get(1).indexOf('=')));
	}catch(StringIndexOutOfBoundsException e){
		System.out.println("Erro de sintaxe");
	}
}
//				if (listaLexemas.get(i).getToken() == Token.PONTO_E_VIRGULA_DUPLO){
//					ehEnd--;
//				}
//				i++;
//		}
//		return i;		
//	}
//	
//	private int getIndexAtribuicao (int index_atual) {
//		int i = index_atual;
//		while (listaLexemas.get(i).getToken() != Token.ATRIBUICAO) {
//			i++;
//		}
//		return i;
//	}
//	
//	private boolean ehOperador (Lexema lexema) {
//		TabelaDeTokens tokens = new TabelaDeTokens();
//		boolean resultado = false;
//		if (tokens.ehOperador(lexema.getToken())) {
//			resultado = true;
//		}
//		return resultado;
//	}
//	
//	private boolean ehOperando (Lexema lexema) {
//		TabelaDeTokens tokens = new TabelaDeTokens();
//		boolean resultado = false;
//		if (tokens.ehOperando(lexema.getToken())) {
//			resultado = true;
//		}
//		return resultado;
//	}
}
